home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Freeware / PowerBackupV1_0 / Source / PowerBackup.ASC < prev   
Encoding:
Text File  |  2002-03-13  |  45.4 KB  |  1,153 lines

  1. '*****************************************************************************
  2. '*                                                                           *
  3. '*   __    _           ___  __      __    _     __               __          *
  4. '*  |  \  / \  |    | |    |  \    |  \  / \   /  \  |  / |   | |  \         *
  5. '*  |__/ |   | |    | |__  |__/    |__/ |   | |      |_/  |   | |__/         *
  6. '*  |    |   | | /\ | |    | \     |  \ |---| |      | \  |   | |            *
  7. '*  |     \_/  |/  \| |___ |  \    |__/ |   |  \__/  |  \  \_/  |     V1.0   *
  8. '*                                                                           *
  9. '*                                                                           *
  10. '*                       written by    CHRISTIAN KARGL                       *
  11. '*                                                                           *
  12. '*                             Copyright   ©2002                             *
  13. '*                                                                           *
  14. '*              Implementation V0.9ß: (AMOS Backup) 16.Sep 1999              *
  15. '*                             V1.00:  6.Okt 2001 -  16.Feb 2002             *
  16. '*                                                                           *
  17. '*        Compiled:  16.Feb 2002 (Options: WB, NoScrn, IncLib, IncErr)       *
  18. '*                                                                           *
  19. '*****************************************************************************
  20. '
  21. '
  22. '  Linked List for Directory Tree
  23. ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24. '  NALLOC (4,+ 0) .... bytes allocated by this item
  25. '  NXTPTR (4,+ 4) .... address to next item (else NULL)
  26. '  PARPTR (4,+ 8) .... address to parent dir item (or NULL for root)
  27. '  FILPTR (4,+12) .... address to sorted file list (or NULL for none)
  28. '  FLBYTE (4,+16) .... number of bytes for all files
  29. '  SLBYTE (4,+20) .... number of bytes selected (init with 0)
  30. '  NFILES (2,+24) .... number of files for this directory item
  31. '  DIRLVL (1,+26) .... directory level = number of sub-dirs from root
  32. '  DRSEL$ (1,+27) .... directory selection (same as file selection)
  33. '  FLSEL$ (N,+28) .... one byte per file: "@" when selected, else "."
  34. '  TNAME$ (T,+N+28) .. select info, tree structure and directory name
  35. '
  36. '
  37. '  Linked List for Files
  38. ' ~~~~~~~~~~~~~~~~~~~~~~~
  39. '  NALLOC (4) ... bytes allocated by this item
  40. '  NXTPTR (4) ... address to next item (else NULL)
  41. '  LENGTH (4) ... file length
  42. '  FNAME$ (?) ... file name
  43. '
  44. '
  45. '  Linked List for Backup History
  46. ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  47. '  NALLOC (4) ... bytes allocated by this item
  48. '  NXTPTR (4) ... address to next item (else NULL)
  49. '  MTEXT$ (?) ... message text to display
  50. '
  51. '
  52. '  Interface programs and variables
  53. ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  54. ' --+------
  55. ' 1 | main program
  56. '   |  0 ... (STR) program version, 3 characters
  57. '   |  1 ... (STR) compilation date, 11 characters
  58. '   +----
  59. '   | Label0 file selection and setup for backup
  60. '   |   0 ... (STR) root dir
  61. '   |   1 ... (STR) backup disc labels
  62. '   |   2 ... (NUM) top position of dir list
  63. '   |   3 ... (NUM) total number of dirs
  64. '   |   4 ... (NUM) top position of file list
  65. '   |   5 ... (NUM) total number of files
  66. '   |   9 ... (NUM) temp var for all cycle buttons
  67. '   +----
  68. '   | Label1 reading source directory (creating dir tree)
  69. '   +----
  70. '   | Label2 backup/restore progress panel (with history list)
  71. '   |   0 ... (NUM) top position of history list
  72. '   |   1 ... (NUM) total number of history lines
  73. '   |   2 ... (NUM) number for first message (title, progress)
  74. '   +----
  75. '   | Label3 final backup report (buttons to saving history)
  76. '   +----
  77. '   | Label4 restore options (with overwrite cycle button)
  78. '   |   0 ... (STR) custom destination to restore files
  79. '   +----
  80. '   | UI BB zonenr,xpos,ypos,textreference (BorderButton)
  81. '   | UI CB zonenr,xpos,ypos,basemsgnum,totalmsgnum (CycleButton)
  82. ' --+------
  83. ' 2 | alert with buttons
  84. '   |  0 ... (STR) alert text
  85. '   |  1 ... (NUM) selected button: 1=OKAY, 2=CANCEL
  86. ' --+------
  87. ' 3 | information box
  88. '   |  0 ... (STR) information text
  89. '
  90. '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  91. '
  92. Set Buffer 20
  93. '
  94. Screen Close 0
  95. 'Break Off : Request Off : Amos Lock : Close Workbench : Wait 100
  96. '
  97. Global VERS$,COMP$,PDIR$,C0$,LF$,SQUEST$,SQFLSH$,YTOP,SECS
  98. Global TREEROOTADRS,MXTREE,FILELISTROOT,MXFILE,NUMDIRS,NUMFILES
  99. Global NUMBYTES,SELBYTES,SQUEFF,REDIRECT,DISKFREE,DISKUSED,MXDISKBYTE
  100. Global NUMDISKS,SPLITNUM,HISTROOTADRS,HISTADRS,NUMHIST,BYTEWRIT,BYTEREAD
  101. Global BKNAME$,SOURCE$,DESTPATH$,DESTFILE$,BKHDRINF$,BKHDRDAT$,NOSIMULATE
  102. '
  103. ' init: set version and compilation date, load program data
  104. '
  105. PDIR$=Dir$ : VERS$="1.0" : COMP$="16-Feb-2002" : FL$="PowerBackup.Dat"
  106. '
  107. If Not Exist(FL$) : Edit : End If : Load FL$ : Resource Bank 16 : Hide
  108. YTOP=52 : SECS=50 : If Ntsc : YTOP=26 : SECS=60 : End If : OKAY=False
  109. Resource Screen Open 1,640,74,0 : Screen Display 1,128,YTOP+64,640,74
  110. Cls 0 : SQUEST$=Chr$(60)+Chr$(54)+Chr$(50)+Chr$(48)+Chr$(46) : C0$=Chr$(0)
  111. BKHDRINF$=Chr.l$($2BAD4815) : BKHDRDAT$=Chr.l$($E0F63C97) : LF$=Chr$(10)
  112. SQFLSH$="(00F,1)(70F,1)(F0F,1)(F07,1)(F00,1)(F70,1)(FF0,1)(7F0,1)(0F0,1)(0F7,1)(0FF,1)(07F,1)"
  113. '
  114. ' check for OS 2.0+, RAM disk, hard disk, powerpacker.library
  115. '
  116. If Deek(Leek(4)+Equ("LIB_VERSION"))<37
  117.    INFO["Sorry, you need OS2.0+ for this program!"]
  118. Else
  119.    If Not Exist("RAM:")
  120.       INFO["Can't find RAM-Disk! Please check your system!"]
  121.    Else
  122.       If Not Exist("Dh0:")
  123.          INFO["No Hard-disk found! Please reboot your system!"]
  124.       Else : OKAY=True
  125.          If Not Exist("LIBS:powerpacker.library")
  126.             INFO["Need 'powerpacker.library' for compression!"]
  127.          End If
  128.       End If
  129.    End If
  130. End If
  131. If OKAY
  132.    '
  133.    ' system okay, check my data
  134.    '
  135.    '+-                                                    -+
  136.    '|  SNIPPED -> Make your own security check if you want |
  137.    '+-                                                    -+
  138.    If OKAY
  139.       '
  140.       ' okay; check for 30 floppy buffers; init main screen
  141.       '
  142.       Erase 20 : FLOPPYADDBUFFERS[0] : NBUFFERS=Param
  143.       If Param<30 : FLOPPYADDBUFFERS[30-NBUFFERS] : End If
  144.       For NR=0 To 31 : Colour NR,0 : Next : Screen Display 1,,YTOP+158,,
  145.       Dialog Open 1,1 : Vdialog$(1,0)=VERS$ : Vdialog$(1,1)=COMP$
  146.       NR=Dialog Run(1) : Wait Vbl : Unpack 11 : Show : Change Mouse 4
  147.       Fade 3 To -1 : Wait 45 : Limit Mouse
  148.       '
  149.       ' main loop (simple, eh?)
  150.       '
  151.       Do
  152.          SL=Dialog(1) : Exit If SL=4
  153.          If SL
  154.             Dialog Freeze 1 : Limit Mouse 128,YTOP To 447,YTOP+231
  155.             On SL Proc MN_ABOUT,MN_BACKUP,MN_RESTORE
  156.             Dialog Unfreeze 1 : Limit Mouse : Wait Vbl : NR=Free
  157.          End If
  158.       Loop : Fade 3 : Wait 45 : Dialog Close : Screen Close 1
  159.       If NBUFFERS<30 : FLOPPYADDBUFFERS[NBUFFERS-30] : End If
  160.    Else
  161.       INFO["Program data corrupted!"]
  162.    End If
  163. End If
  164. Dir$=PDIR$ : Erase All : Edit
  165. 'Dir$=PDIR$ : Erase All : System
  166. '
  167. ' Main Procedures
  168. '
  169. Procedure MN_ABOUT
  170.    '
  171.    ' init scrolled graphics on hidden screen
  172.    '
  173.    PAGE=4 : Resource Screen Open 2,256,384,0 : Screen Hide 2 : Cls 6
  174.    AD=Start(10) : Unpack 11 : Cls 6,8,4 To 12,70 : Cls 6,238,4 To 240,70
  175.    Get Block 8,8,5,240,64 : Cls 6 : Put Block 8,0,0 : Ink 2,6 : YP=64
  176.    For PG=1 To PAGE
  177.       For LI=0 To 5 : CL=Peek(AD) : LL=Peek(AD+1) : TT$=Peek$(AD+2,LL)
  178.          Add AD,LL+2 : XX=116-4*LL : YY=YP+9 : Add YP,10 : Gr Writing 0
  179.          Ink 0 : Text XX-1,YY,TT$ : Text XX+1,YY,TT$ : Text XX,YY-1,TT$
  180.          Text XX,YY+1,TT$ : Ink CL : Text XX,YY,TT$ : Gr Writing 1
  181.       Next : Add YP,4
  182.    Next : Put Block 8,0,YP : Inc PAGE : Del Block 8 : Screen 1
  183.    Get Block 8,248,4,384,66 : Change Mouse 5 : Ink 0,3 : YP=0
  184.    Set Pattern 30 : Bar 248,4 To 631,69 : Set Pattern 0 : PG=0
  185.    '
  186.    ' scroll info text; wait for key or mouse button each page
  187.    '
  188.    Do : Inc PG
  189.       For LI=0 To 63 : Inc YP
  190.          Screen Copy 2,4,YP,230,YP+64 To 1,12,5 : Wait Vbl
  191.       Next : Exit If PG=PAGE
  192.       Clear Key : Repeat : Until Mouse Click or Inkey$>""
  193.    Loop : Change Mouse 4 : Put Block 8 : Del Block 8 : Wait Vbl
  194.    Screen Close 2
  195. End Proc
  196. Procedure MN_BACKUP
  197.    '
  198.    ' init file selection; appear screen
  199.    '
  200.    SOURCE$="" : BKNAME$="Backup"
  201.    REDIRECT=False : INSTALL=False : TREEROOTADRS=0 : FILELISTROOT=0
  202.    NUMDIRS=0 : MXTREE=0 : MXFILE=0 : NUMFILES=0 : NUMBYTES=0 : SELBYTES=0
  203.    SQUEFF=0 : Resource Screen Open 2,640,232,0 : Cls 0 : Pen 2
  204.    Paper 6 : Screen Display 2,128,YTOP+248,640,232 : Reserve Zone 2
  205.    Set Zone 1,32,48 To 319,175 : Set Zone 2,368,48 To 607,175 : REDRAW=8
  206.    Dialog Open 2,1,16,4096 : Vdialog$(2,0)=SOURCE$ : Vdialog$(2,1)=BKNAME$
  207.    Vdialog(2,3)=0 : Vdialog(2,5)=0 : SL=Dialog Run(2,0) : CONTINUE=1
  208.    For YP=240 To 0 Step -8 : Screen Display 2,,YTOP+YP,, : Wait Vbl : Next
  209.    '
  210.    ' main backup selection loop
  211.    '
  212.    Repeat
  213.       '
  214.       ' check for click on list areas; else check dialog
  215.       '
  216.       If Mouse Click
  217.          MZ=Mouse Zone : PS=(Y Screen(Y Mouse)-48)/8
  218.          If MZ=1
  219.             If DRTOP+PS<MXTREE : MK=Mouse Key
  220.                If MK=1 : SL=13 : Else If MK=2 : SL=14 : End If
  221.             End If
  222.          Else If MZ=2
  223.             If FLTOP+PS<MXFILE : SL=15 : End If
  224.          End If
  225.       Else
  226.          SL=Dialog(2)
  227.       End If
  228.       '
  229.       ' check for selection
  230.       '
  231.       If SL
  232.          Dialog Freeze 2 : Window 0 : Wait Vbl
  233.          If SL=1
  234.             '
  235.             ' change source dir: if exist read new source directory
  236.             '
  237.             TT$=Path$(Rdialog$(2,1)+"/")
  238.             If Exist(TT$) : MT=MXTREE
  239.                ND=NUMDIRS : NF=NUMFILES : NB=NUMBYTES : SB=SELBYTES
  240.                Get Block 8,0,0,640,232 : Ink 0,3 : Set Pattern 30
  241.                Bar 0,0 To 639,231 : Set Pattern 0 : Dialog Open 3,1
  242.                SL=Dialog Run(3,1) : MAKE_DIRTREE[TT$] : Dialog Close 3
  243.                '
  244.                ' delete old tree and update vars, else restore old values
  245.                '
  246.                If Param>0 : SOURCE$=TT$ : DRTOP=0 : FLTOP=0 : REDRAW=7
  247.                   AD=TREEROOTADRS : TREEROOTADRS=Param : DELETE_DIRTREE[AD]
  248.                   FILELISTROOT=TREEROOTADRS : MXFILE=Deek(FILELISTROOT+24)
  249.                Else : MXTREE=MT
  250.                   NUMDIRS=ND : NUMFILES=NF : NUMBYTES=NB : SELBYTES=SB
  251.                   If Param : INFO["Sorry, I'm low on memory!"]
  252.                   Else : INFO["Directory tree setup aborted."] : End If
  253.                End If : Put Block 8 : Del Block 8 : Gosub DISPLAY : Wait Vbl
  254.             End If : Dialog Update 2,1,SOURCE$
  255.          Else If SL=2
  256.             '
  257.             ' remove path character; ask if user wants to redirect backup
  258.             '
  259.             TT$=Rdialog$(2,2) : PS=Instr(TT$,">>")+2
  260.             If PS=2
  261.                BKNAME$=TT$-" "-"/"-":" : REDIRECT=False
  262.             Else If PS>3
  263.                If Exist(Mid$(TT$,PS))
  264.                   ALERT["Redirect backup to '"+Mid$(TT$,PS)+"' ?"]
  265.                   If Param=1 : BKNAME$=TT$ : REDIRECT=True : End If
  266.                End If
  267.             End If : Dialog Update 2,2,BKNAME$
  268.          Else If SL<6
  269.             DRTOP=Vdialog(2,2) : REDRAW=1 : Gosub DISPLAY
  270.          Else If SL<9
  271.             FLTOP=Vdialog(2,4) : REDRAW=2 : Gosub DISPLAY
  272.          Else If SL=9
  273.             INSTALL=Rdialog(2,9) : REDRAW=2 : Gosub DISPLAY
  274.          Else If SL=10
  275.             SQUEFF=Rdialog(2,10)/2 : REDRAW=8 : Gosub DISPLAY
  276.          Else If SL<13
  277.             '
  278.             ' check to leave selection loop
  279.             '
  280.             CONTINUE=SL-12
  281.             If SL=10 and SELBYTES=0
  282.                INFO["No data selected to backup!"] : CONTINUE=1
  283.             Else If REDIRECT
  284.                TT$=Disc Info$(Mid$(BKNAME$,Instr(BKNAME$,">>")+2))
  285.                MX=Val(Mid$(TT$,Instr(TT$,":")+1)) : NR=SELBYTES
  286.                If SQUEFF : NR=(NR/100)*Asc(Mid$(SQUEST$,SQUEFF)) : End If
  287.                '
  288.                ' check if enough disc space when redirecting
  289.                '
  290.                If MX<NR
  291.                   INFO["Not enough disc space to redirect!"] : CONTINUE=1
  292.                Else If MX<104*(NR/100)
  293.                   ALERT["Free disc space may be insufficent. Continue?"]
  294.                   If Param>1 : CONTINUE=1 : End If
  295.                End If
  296.             End If
  297.          Else If SL=13
  298.             '
  299.             ' left click on tree area -> select dir
  300.             '
  301.             MOVE_TO_ENTRY[TREEROOTADRS,DRTOP+PS]
  302.             If Param : ADRS=Param : REDRAW=3
  303.                SNEW=110-Peek(ADRS+27) : MX=Peek(ADRS+26)
  304.                Repeat
  305.                   NR=Deek(ADRS+24)+1 : AD=ADRS+27
  306.                   While NR : Poke AD,SNEW : Inc AD : Dec NR : Wend
  307.                   If SNEW=64 : NR=Leek(ADRS+16) Else NR=0 : End If
  308.                   Add SELBYTES,NR-Leek(ADRS+20) : Loke ADRS+20,NR
  309.                   ADRS=Leek(ADRS+4) : Exit If ADRS=0
  310.                Until Peek(ADRS+26)<=MX : Gosub DISPLAY
  311.             End If
  312.          Else If SL=14
  313.             '
  314.             ' right click on tree area -> display files
  315.             '
  316.             MOVE_TO_ENTRY[TREEROOTADRS,DRTOP+PS]
  317.             If Param : FILELISTROOT=Param : FLTOP=0
  318.                MXFILE=Deek(Param+24) : REDRAW=7 : Gosub DISPLAY
  319.             End If
  320.          Else If SL=15
  321.             '
  322.             ' click on file area -> select file
  323.             '
  324.             MOVE_TO_ENTRY[Leek(FILELISTROOT+12),FLTOP+PS]
  325.             If Param
  326.                BYTE=Leek(Param+8) : ADRS=FILELISTROOT : REDRAW=3
  327.                AD=ADRS+FLTOP+PS+28 : SNEW=110-Peek(AD) : Poke AD,SNEW
  328.                If SNEW=46 : BYTE=-BYTE : End If : Add SELBYTES,BYTE
  329.                NR=Leek(ADRS+20)+BYTE : If NR : SL=64 Else SL=46 : End If
  330.                Loke ADRS+20,NR : Poke ADRS+27,SL : Gosub DISPLAY
  331.             End If
  332.          End If : Dialog Unfreeze 2 : Wait Vbl
  333.       End If
  334.    Until CONTINUE<1 : Dialog Close 2
  335.    '
  336.    ' if not aborted, check for redirection
  337.    '
  338.    If CONTINUE : DESTPATH$="DF0:"
  339.       If REDIRECT : PS=Instr(BKNAME$,">>") : TT$=Mid$(BKNAME$,PS+2)
  340.          BKNAME$=Left$(BKNAME$,PS-1) : NR=Asc(Right$(TT$,1)) : Ink 0,3
  341.          If NR<>47 and NR<>58 : TT$=TT$+"/" : End If : DESTPATH$=TT$
  342.          Set Pattern 30 : Bar 0,0 To 639,231 : Set Pattern 0 : BYTE=488
  343.          NR=1760 : DISKUSED=0 : Dialog Open 3,1 : SL=Dialog Run(3,6)
  344.          Do
  345.             SL=Dialog(3) : Exit If SL>3
  346.             If SL
  347.                If Rdialog(3,1) : NR=3520 Else NR=1760 : End If
  348.                If Rdialog(3,2) : BYTE=512 Else BYTE=488 : End If
  349.                MX=BYTE*(NR-4) : Window 0 : Print At(61,13);Lsstr$(MX/1024,4)
  350.                SB=Min(1024*Rdialog(3,3),MX/2) : Dialog Update 3,3,SB/1024
  351.             End If
  352.          Loop : CONTINUE=(SL=4)
  353.          MXDISKBYTE=BYTE*((1730*NR)/1760-6) : Dialog Close 3 : Wait Vbl
  354.       End If
  355.       If CONTINUE
  356.          '
  357.          ' init history messages
  358.          '
  359.          Timer=0 : HISTROOTADRS=0 : HISTADRS=0 : NUMHIST=0 : DRTOP=0
  360.          GTDATETIME : HISTORYENTRY["Starting backup: "+Param$] : NF=0
  361.          Dec SQUEFF : HISTORYENTRY["Writing to: '"+DESTPATH$+"'"+LF$]
  362.          '
  363.          ' calculate number of selected files
  364.          '
  365.          NUMDISKS=1 : BYTEWRIT=0 : BYTEREAD=0 : MX=0 : ADRS=TREEROOTADRS
  366.          While ADRS : AD=ADRS+28 : NR=Deek(ADRS+24) : ADRS=Leek(ADRS+4)
  367.             While NR : Add MX,Peek(AD)/64 : Inc AD : Dec NR : Wend
  368.          Wend : TT$=Chr.l$(MX xor $A45B918D)+Chr.l$(MX xor $C2370E6F)
  369.          '
  370.          ' init backup dialog, ask for first disc and write init header
  371.          '
  372.          Fade 2 : Wait 30 : Cls 0 : Dialog Open 2,1 : Vdialog(2,0)=0
  373.          Vdialog(2,1)=NUMHIST : Vdialog(2,2)=28 : RN=Dialog Run(2,2)
  374.          DISPLAY_HISTORY[0] : Fade 3 To 1 : Wait 45 : REQUEST_BACKDISC[1]
  375.          DISKUSED=SB+16 : Print #1,"PPBACK10"+TT$; : ADRS=TREEROOTADRS
  376.          '
  377.          ' add required data and program to start from first disc
  378.          '
  379.          If INSTALL : Add DISKUSED,169824
  380.             SOURCE$=Extpath$(PDIR$) : TT$="powerpacker.library"
  381.             Mkdir "Libs" : Trap File Copy "LIBS:"+TT$ To "Libs/"+TT$
  382.             TT$=Command Name$ : File Copy SOURCE$+TT$ To TT$
  383.             TT$=TT$+".info" : File Copy SOURCE$+TT$ To TT$
  384.             TT$="PowerBackup.Dat" : File Copy SOURCE$+TT$ To TT$
  385.             HISTORYENTRY["Copying program and data to first disc."+LF$]
  386.          End If
  387.          '
  388.          ' read through directory tree and backup selected files
  389.          '
  390.          While ADRS : FLADRS=Leek(ADRS+12) : Loke ADRS+12,0
  391.             If FLADRS>0 and Peek(ADRS+27)=64 : CREATE_DIRTREE_PATH[ADRS]
  392.                TT$=Param$ : FADR=FLADRS : NR=Deek(ADRS+24) : AD=ADRS+28
  393.                While NR
  394.                   If Peek(AD)=64 : PS=Max(NUMHIST-8,0)
  395.                      BACKUP_FILE[TT$+Peek$(FADR+12,Leek(FADR),C0$)]
  396.                      '
  397.                      ' update dialog
  398.                      '
  399.                      If Vdialog(2,0)=PS
  400.                         DRTOP=Max(NUMHIST-8,0) : DISPLAY_HISTORY[DRTOP]
  401.                      Else If Dialog(2)
  402.                         DRTOP=Vdialog(2,0) : DISPLAY_HISTORY[DRTOP]
  403.                      End If
  404.                      Dialog Update 2,1,DRTOP,8,NUMHIST : Inc NF
  405.                      Vdialog(2,1)=NUMHIST : Dialog Update 2,2,0,NF,MX
  406.                   End If : Inc AD : Dec NR : FADR=Leek(FADR+4)
  407.                Wend
  408.             End If : DELETE_LIST[FLADRS] : ADRS=Leek(ADRS+4)
  409.          Wend
  410.          '
  411.          ' done; close file and display final report; save/delete history
  412.          '
  413.          Print #1,BKHDRINF$;"¦END"; : Close 1 : Ink 0,3 : Set Pattern 30
  414.          Bar 0,0 To 639,231 : Set Pattern 0 : SL=Timer/SECS : NR=SL mod 60
  415.          Dialog Close 2 : Wait 5 : Dialog Open 2,1 : RN=Dialog Run(2,3)
  416.          Wait Vbl : GTDATETIME : HISTORYENTRY["Finished backup: "+Param$]
  417.          SL=SL/60 : BYTEREAD=Max(BYTEREAD,100) : TT$=Lsstr$(NUMDISKS,4)
  418.          HISTORYENTRY[Resource$(34)+Space$(10)+TT$] : Print At(55,11);TT$
  419.          TT$=Lsstr$(BYTEWRIT,8) : HISTORYENTRY[Resource$(35)+" "+TT$]
  420.          Print At(51,12);TT$ : TT$=Lsstr$(BYTEWRIT/(BYTEREAD/100),3)+"%"
  421.          HISTORYENTRY[Resource$(36)+Space$(6)+TT$] : Print At(55,13);TT$
  422.          TT$=Lzstr$(SL/60,2)+":"+Lzstr$(SL mod 60,2)+":"+Lzstr$(NR,2)
  423.          HISTORYENTRY[Resource$(37)+Space$(7)+TT$] : Print At(51,14);TT$
  424.          Repeat : SL=Dialog(2) : Until SL>0 : Dialog Close 2 : Wait 5
  425.          If SL=1 : HISTORY_SAVE : End If : DELETE_LIST[HISTROOTADRS]
  426.       End If
  427.    End If
  428.    '
  429.    ' delete directory tree
  430.    '
  431.    For YP=0 To 240 Step 8 : Screen Display 2,,YTOP+YP,, : Wait Vbl : Next
  432.    Screen Close 2 : DELETE_DIRTREE[TREEROOTADRS] : Pop Proc
  433.    '
  434.    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  435.    ' redraw backup selection display
  436.    '
  437.    DISPLAY:
  438.    NR=SELBYTES : If INSTALL : AD=169824 Else AD=0 : End If
  439.    If SQUEFF : NR=(NR/100)*Asc(Mid$(SQUEST$,SQUEFF)) : End If
  440.    Add NR,AD : NUMDDISK=NR/858880+1 : NUMHDISK=NR/1717760+1
  441.    Print At(11,23);Lsstr$(NUMDIRS,6);At(27,23);Lsstr$(NUMFILES,6)
  442.    Print At(43,23);Lsstr$(NUMBYTES,9);At(66,23);Lsstr$(SELBYTES,9)
  443.    Print At(39,25);Lsstr$(NUMDDISK,4);At(48,25);Lsstr$(NUMHDISK,4)
  444.    '
  445.    ' check other updates
  446.    '
  447.    If REDRAW and 1 : DISPLAY_DIRS[DRTOP] : End If
  448.    If REDRAW and 2 : DISPLAY_FILES[FLTOP] : End If
  449.    If REDRAW and 4 : Dialog Update 2,1,SOURCE$
  450.       Vdialog(2,3)=MXTREE : Dialog Update 2,5,DRTOP,16,MXTREE
  451.       Vdialog(2,5)=MXFILE : Dialog Update 2,8,FLTOP,16,MXFILE
  452.    End If : REDRAW=0
  453.    Return
  454.    '
  455. End Proc
  456. Procedure MN_RESTORE
  457.    '
  458.    ' init restore options; appear screen
  459.    '
  460.    Resource Screen Open 2,640,232,0
  461.    Cls 0 : Paper 6 : Pen 2 : Screen Display 2,128,YTOP+248,640,232
  462.    DESTPATH$="" : Dialog Open 2,1 : Vdialog$(2,0)="" : SL=Dialog Run(2,4)
  463.    For YP=240 To 0 Step -8 : Screen Display 2,,YTOP+YP,, : Wait Vbl : Next
  464.    '
  465.    ' wait for actions; read settings
  466.    '
  467.    Repeat
  468.       SL=Dialog(2)
  469.       If SL=3 : TT$=Rdialog$(2,3) : OK=Exist(TT$)
  470.          If OK=False : ALERT["Directory not found! Create?"]
  471.             If Param=1 : CREATE_DIR[TT$] : OK=True : End If
  472.          End If
  473.          If OK : DESTPATH$=Extpath$(TT$)
  474.             Dialog Update 2,2,1 : Dialog Update 2,3,TT$
  475.          End If
  476.       End If
  477.    Until SL>4 : NOSIMULATE=(Rdialog(2,1)=0)
  478.    REDIRECT=Rdialog(2,2) : OVRTYP=Rdialog(2,4)/2 : Dialog Close 2
  479.    If Not NOSIMULATE : REDIRECT=False : OVRTYP=2 : End If
  480.    '
  481.    ' if not aborted: start dialog and request first disc
  482.    '
  483.    If SL=5
  484.       Fade 2 : Wait 30 : Cls 0 : Dialog Open 2,1 : Vdialog(2,0)=0
  485.       Vdialog(2,1)=0 : Vdialog(2,2)=46 : SL=Dialog Run(2,2) : Wait Vbl
  486.       Dialog Freeze 2 : Fade 3 To 1 : Wait 45 : Dialog Open 7,3
  487.       Vdialog$(7,0)="Please insert first disc into drive DF0:"
  488.       SL=Dialog Run(7) : Repeat : Until Exist("DF0:") : Dialog Close 7
  489.       Wait Vbl : SOURCE$="DF0:Backup0001.DAT0" : TT$=Disc Info$("DF0:")
  490.       BKNAME$=Left$(TT$,Instr(TT$,":")-1) : PS=Instr(BKNAME$,"_#")
  491.       '
  492.       ' check header informations
  493.       '
  494.       If PS : BKNAME$=Left$(BKNAME$,PS-1)
  495.          If Exist(SOURCE$) : Open In 1,SOURCE$ : HD$=Input$(1,8)
  496.             TT$=Input$(1,8) : CHCK=Asc.l(Right$(TT$,4)) xor $C2370E6F
  497.             NUMFILES=Asc.l(Left$(TT$,4)) xor $A45B918D : NUMDISKS=1
  498.             '
  499.             ' if header okay, init history messages
  500.             '
  501.             If HD$="PPBACK10" and NUMFILES=CHCK : Timer=0 : HTOP=0
  502.                HISTROOTADRS=0 : HISTADRS=0 : NUMHIST=0 : SPLITNUM=0
  503.                GTDATETIME : HISTORYENTRY["Starting restore: "+Param$]
  504.                '
  505.                ' check redirection and simulation; unfreeze dialog
  506.                '
  507.                If NOSIMULATE : TT$="Writing data to "
  508.                   If REDIRECT : TT$=TT$+"'"+DESTPATH$+"'."
  509.                   Else : TT$=TT$+"original location." : End If
  510.                Else : TT$="Simulating file restoration." : End If
  511.                HISTORYENTRY[TT$+LF$] : DISPLAY_HISTORY[0] : FLOKAY=0
  512.                FLERRS=0 : FLSKIP=0 : FLOVER=0 : Vdialog(2,1)=NUMHIST
  513.                Dialog Update 2,1,DRTOP,8,NUMHIST : Dialog Unfreeze 2
  514.                '
  515.                ' main restore loop; get next file infos; check headers
  516.                '
  517.                For FL=1 To NUMFILES : SL=Max(NUMHIST-8,0)
  518.                   If Input$(1,4)=BKHDRINF$ : TT$=Input$(1,4)
  519.                      Exit If TT$="¦END" : INFO$=TT$+Input$(1,22)
  520.                      FLEN=Asc.w(Input$(1,2)) : FILE$=Input$(1,FLEN)
  521.                      If Input$(1,4)=BKHDRDAT$ : OK=True
  522.                         '
  523.                         ' check dir, check existing files, restore file
  524.                         '
  525.                         If NOSIMULATE
  526.                            If REDIRECT
  527.                               FILE$=DESTPATH$+Mid$(FILE$,Instr(FILE$,":")+1)
  528.                            End If
  529.                            If Exist(FILE$) : OK=(OVRTYP>1)
  530.                               If OVRTYP=1
  531.                                  ALERT["Overwrite file?"] : OK=(Param=1)
  532.                               End If : If OK : Inc FLOVER : End If
  533.                            End If
  534.                         End If
  535.                         If OK : RESTOR_FILE[FILE$,INFO$]
  536.                            If Param : Inc FLOKAY Else Inc FLERRS : End If
  537.                         Else : Inc FLSKIP
  538.                            FILE$="Skipping '"+FILE$+"'" : Gosub SKIPDATA
  539.                         End If
  540.                      Else : Inc FLERRS
  541.                         FILE$="Error! Missing header." : Gosub SKIPDATA
  542.                      End If
  543.                   Else : Inc FLERRS
  544.                      FILE$="Error! Missing header." : Gosub SKIPDATA
  545.                   End If
  546.                   '
  547.                   ' update dialog sliders
  548.                   '
  549.                   If Vdialog(2,0)=SL
  550.                      DRTOP=Max(NUMHIST-8,0) : DISPLAY_HISTORY[DRTOP]
  551.                   Else If Dialog(2)
  552.                      DRTOP=Vdialog(2,0) : DISPLAY_HISTORY[DRTOP]
  553.                   End If
  554.                   Vdialog(2,1)=NUMHIST : Dialog Update 2,1,DRTOP,8,NUMHIST
  555.                   Dialog Update 2,3,0,FL,NUMFILES : Wait Vbl
  556.                Next
  557.                '
  558.                ' done; display final report; save/delete history
  559.                '
  560.                Dialog Freeze 2 : SL=Timer/SECS : GTDATETIME
  561.                HISTORYENTRY["Finished restore: "+Param$] : Ink 0,3
  562.                Set Pattern 30 : Bar 0,0 To 639,231 : Set Pattern 0
  563.                Dialog Open 3,1 : RN=Dialog Run(3,5) : Wait Vbl
  564.                TT$=Lsstr$(FLOKAY,6) : HISTORYENTRY[Resource$(49)+" "+TT$]
  565.                Print At(51,11);TT$ : TT$=Lsstr$(FLSKIP,6) : NR=SL mod 60
  566.                HISTORYENTRY[Resource$(50)+"    "+TT$] : Print At(51,12);TT$
  567.                TT$=Lsstr$(FLOVER,6) : HISTORYENTRY[Resource$(51)+"   "+TT$]
  568.                Print At(51,13);TT$ : TT$=Lsstr$(FLERRS,6) : SL=SL/60
  569.                HISTORYENTRY[Resource$(52)+"   "+TT$] : Print At(51,14);TT$
  570.                TT$=Lzstr$(SL/60,2)+":"+Lzstr$(SL mod 60,2)+":"+Lzstr$(NR,2)
  571.                HISTORYENTRY[Resource$(53)+" "+TT$] : Print At(49,15);TT$
  572.                Repeat : SL=Dialog(3) : Until SL>0 : Dialog Close 3 : Wait 5
  573.                If SL=1 : HISTORY_SAVE : End If : DELETE_LIST[HISTROOTADRS]
  574.             Else
  575.                INFO["First backup data has corrupted file header!"]
  576.             End If : Close 1
  577.          Else
  578.             INFO["Can't find first backup data file!"]
  579.          End If
  580.       Else
  581.          INFO["Wrong backup disc name format!"]
  582.       End If
  583.       Dialog Close 2
  584.    End If
  585.    '
  586.    ' done; remove screen
  587.    '
  588.    For YP=0 To 240 Step 8 : Screen Display 2,,YTOP+YP,, : Wait Vbl : Next
  589.    Screen Close 2 : Pop Proc
  590.    '
  591.    ' special sub routine for skipping current data to next file
  592.    '
  593.    SKIPDATA:
  594.    Change Mouse 5 : Flash 18,SQFLSH$ : Cls 6,56,104 To 584,128
  595.    Wait 5 : HISTORYENTRY["("+Ct Time$(Current Time)+") "+FILE$]
  596.    TT$="Searching for header information." : HISTORYENTRY["  "+TT$+LF$]
  597.    PS=Len(FILE$) : If PS>66 : FILE$=Cutstr$(FILE$,11 To PS-55) : End If
  598.    Print At(7,13);FILE$;At(9,14);TT$;".." : Reserve As Work 20,1024
  599.    AD=Start(20) : PS=Pof(1) : SZ=Lof(1)-PS
  600.    '
  601.    ' read bytes of file; check for end of file; set file position
  602.    '
  603.    Do
  604.       If Eof(1) : Inc SPLITNUM
  605.          Close 1 : Wait 5 : Right$(SOURCE$,1)=Chr$(SPLITNUM+48)
  606.          If Not Exist(SOURCE$)
  607.             Inc NUMDISKS : REQUEST_RESTDISC[NUMDISKS]
  608.          End If : Open In 1,SOURCE$ : Wait 5 : PS=0 : SZ=Lof(1)
  609.       End If
  610.       Poke$ AD,Input$(1,Min(SZ,1024)) : Wait Vbl
  611.       SZ=Max(SZ-1024,0) : FLEN=Hunt(AD To AD+1024,BKHDRINF$)
  612.       If FLEN>0 : Add PS,FLEN-AD : Exit : End If : Add PS,1024
  613.    Loop : Pof(1)=PS : Flash Off
  614.    Colour 18,$C60 : Change Mouse 4 : Erase 20 : Wait Vbl
  615.    Return
  616.    '
  617. End Proc
  618. Procedure GTDATETIME
  619.    '
  620.    ' formated date & time: "www dd-mmm-yyyy at hh:mm:ss."
  621.    '
  622.    DATE=Current Date : TT$=" at "+Ct Time$(Current Time)+"."
  623.    TT$=Left$(Cd Date$(DATE),11)+Lsstr$(Cd Year(DATE),4)+TT$
  624. End Proc[TT$]
  625. '
  626. ' Backup Procedures
  627. '
  628. Procedure DISPLAY_DIRS[DTOP]
  629.    '
  630.    ' display directory tree starting at DTOP
  631.    '
  632.    MOVE_TO_ENTRY[TREEROOTADRS,DTOP] : AD=Param
  633.    If AD : ITEM=0 : YP=6
  634.       '
  635.       ' okay, print next 16 entries
  636.       '
  637.       While ITEM<16
  638.          TT$=Peek$(AD+Deek(AD+24)+28,Leek(AD),C0$) : YY=8*YP
  639.          If AD=FILELISTROOT : Paper 4 Else Paper 0 : End If
  640.          If Peek(AD+27)=64 : Pen 1 Else Pen 3 : End If : PS=1
  641.          Do
  642.             A$=Mid$(TT$,PS,1) : Inc PS : XX=16*PS
  643.             Exit If A$="»" : NR=Instr("|+-",A$)
  644.             If NR : Resource Unpack NR+35,XX,YY
  645.             Else Cls 0,XX,YY To XX+16,YY+8 : End If
  646.          Loop : NR=40-2*PS : A$=Mid$(TT$,Min(PS,NR))
  647.          '
  648.          ' >>> PROBLEM: DirName + DirStructure too long ??
  649.          '
  650.          Print At(2*PS,YP);A$;Paper$(0);Space$(NR-Len(A$));
  651.          Inc YP : Inc ITEM : AD=Leek(AD+4) : Exit If AD=0
  652.       Wend : If ITEM<16 : Cls 0,32,8*YP To 320,176 : End If
  653.       Wait Vbl : Paper 6 : Pen 2
  654.    End If
  655. End Proc
  656. Procedure DISPLAY_FILES[FTOP]
  657.    '
  658.    ' display next 16 file names starting at FTOP
  659.    '
  660.    MOVE_TO_ENTRY[Leek(FILELISTROOT+12),FTOP]
  661.    If Param : ADRS=Param
  662.       ITEM=0 : YP=6 : Paper 0 : STRT=FILELISTROOT+FTOP+28
  663.       While ITEM<14
  664.          FL$=Peek$(ADRS+12,22,C0$) : FLEN=Leek(ADRS+8)
  665.          If Peek(STRT+ITEM)=64 : Pen 1 Else Pen 3 : End If
  666.          Print At(46,YP);FL$;Space$(22-Len(FL$));Lsstr$(FLEN,8)
  667.          Inc YP : ADRS=Leek(ADRS+4) : Exit If ADRS=0 : Inc ITEM
  668.       Wend : If ITEM<14 : Cls 0,368,8*YP To 608,160 : End If
  669.       Paper 6 : Pen 2
  670.    Else
  671.       Cls 0,368,48 To 608,160
  672.    End If
  673. End Proc
  674. Procedure REQUEST_BACKDISC[DN]
  675.    '
  676.    ' wait for next disc
  677.    '
  678.    TT$=Lzstr$(DN,4) : SPLITNUM=0 : DISKUSED=0 : Dir$="RAM:"
  679.    NAME$=BKNAME$+"_#"+TT$ : DESTFILE$="Backup"+TT$+".DAT0"
  680.    If REDIRECT
  681.       '
  682.       ' redirecting -> create new directory for next floppy
  683.       '
  684.       TT$=DESTPATH$+NAME$ : DISKFREE=MXDISKBYTE
  685.       If Not Exist(TT$) : Mkdir TT$ : End If : Dir$=TT$
  686.    Else
  687.       '
  688.       ' else wait for a new real floppy disc in drive DF0:
  689.       '
  690.       Get Block 8,0,0,640,232 : Wait Vbl : Ink 0,3
  691.       Set Pattern 30 : Bar 0,0 To 639,231 : Set Pattern 0
  692.       Do
  693.          '
  694.          ' remove any disc in drive DF0: first
  695.          '
  696.          If Exist("DF0:") : Dialog Open 3,3
  697.             Vdialog$(3,0)="Please remove disc from DF0:" : RR=Dialog Run(3)
  698.             Wait Vbl : Repeat : Until Not Exist("DF0:") : Dialog Close 3
  699.          End If
  700.          '
  701.          ' ask for next backup disc; get disc infos; ask to use it
  702.          '
  703.          Dialog Open 3,3
  704.          Vdialog$(3,0)="Please insert backup disc"+Str$(DN)+" into DF0:"
  705.          RR=Dialog Run(3) : Wait Vbl : Repeat : Until Exist("DF0:")
  706.          Dialog Close 3 : Wait Vbl : TT$=Disc Info$("DF0:")
  707.          DF$=Right$(TT$,10)-" " : TT$=Left$(TT$,Len(TT$)-10)
  708.          ALERT[DF$+" bytes free on disc '"+TT$+"'. Continue?"]
  709.          If Param=1
  710.             '
  711.             ' relabel disc (DOS function call returns 0 on failure)
  712.             '
  713.             DISKFREE=Val(DF$) : TT$="DF0:" : Dreg(1)=Varptr(TT$)
  714.             Dreg(2)=Varptr(NAME$) : Exit If Doscall(Lvo("Relabel"))
  715.             INFO["ERROR! Can't relabel disc in drive DF0:"] : Clear Key
  716.          End If : Wait 10
  717.       Loop : Put Block 8 : Del Block 8 : Wait Vbl : Dir$="DF0:"
  718.    End If : Trap Kill DESTFILE$ : Open Out 1,DESTFILE$
  719.    '
  720. End Proc
  721. Procedure BACKUP_FILE[FILE$]
  722.    '
  723.    ' write file FILE$ (with full path) into backup file
  724.    '
  725.    HISTORYENTRY["("+Ct Time$(Current Time)+") Loading '"+FILE$+"'"]
  726.    Examine Object FILE$ : FLSIZE=Object Size : FLSUMM=0 : SQSIZE=0
  727.    SQSUMM=0 : Cls 6,56,104 To 584,128 : Print At(7,13);Right$(FILE$,66)
  728.    '
  729.    ' check for data to load
  730.    '
  731.    If FLSIZE>0 : BLEN=(FLSIZE+3) and $FFFFFFFC
  732.       Print At(9,14);"Loading... "; : Trap Reserve As Work 20,BLEN
  733.       If Errtrap=0
  734.          AD=Start(20) : Fill AD To AD+BLEN,0 : Bload FILE$,AD
  735.          Wait 5 : FLSUMM=Bank Checksum(20) : Print "Done."
  736.          '
  737.          ' squash file with powerpacker.library ?
  738.          '
  739.          If SQUEFF>=0 and FLSIZE>99 : Change Mouse 5
  740.             Flash 18,SQFLSH$ : Print At(11,15);"Squashing... ";
  741.             Wait 5 : Trap Pptodisk "RAM:Temp",20,SQUEFF : Flash Off
  742.             Colour 18,$C60 : Change Mouse 4 : Wait Vbl : SQSIZE=FLSIZE
  743.             If Errtrap=0
  744.                Open In 2,"Ram:Temp" : SQSIZE=Lof(2) : Close 2 : Wait Vbl
  745.                BLEN=(SQSIZE+3) and $FFFFFFFC : Reserve As Work 20,BLEN
  746.                AD=Start(20) : Fill AD To AD+BLEN,0 : Bload "Ram:Temp",AD
  747.             End If
  748.          End If
  749.       End If
  750.    End If
  751.    '
  752.    ' print messages and save data from bank 20 to backup file
  753.    '
  754.    If Length(20)>0
  755.       If FLSIZE=0
  756.          INFO$="Storing empty file" : Locate 9,14 : HMSG$=INFO$
  757.       Else
  758.          SZ$=" ("+Mid$(Str$(FLSIZE),2)+" bytes)"
  759.          If SQSIZE=0 : INFO$="Saving original file" : Locate 11,15
  760.             HMSG$=INFO$+SZ$ : SQSUMM=FLSUMM : SQSIZE=FLSIZE
  761.          Else If SQSIZE<FLSIZE
  762.             SQSUMM=Bank Checksum(20) : INFO$="Saving squashed file"
  763.             TT$=Mid$(Str$(Int(SQSIZE/(FLSIZE/1000.0))/10.0),2)+"% ="
  764.             HMSG$=INFO$+" ("+TT$+Str$(SQSIZE)+"/"+Mid$(SZ$,3)
  765.          Else
  766.             INFO$="FAILED! Saving original file" : SQSIZE=FLSIZE
  767.             HMSG$="Squashing "+INFO$+SZ$ : SQSUMM=FLSUMM
  768.          End If
  769.       End If
  770.       Print INFO$;"... "; : FL=Len(FILE$) : FLPY=(DESTPATH$="DF0:")
  771.       Add DISKUSED,36+FL : Add BYTEREAD,FLSIZE : Add BYTEWRIT,SQSIZE
  772.       Print #1,BKHDRINF$+Chr.l$(FLSIZE)+Chr.l$(FLSUMM)+Chr.l$(SQSIZE);
  773.       Print #1,Chr.l$(SQSUMM)+Chr.l$(Object Date)+Chr.l$(Object Time);
  774.       Print #1,Chr.w$(Object Protection)+Chr.w$(FL)+FILE$+BKHDRDAT$;
  775.       '
  776.       ' check disc space and file limit (216K); write data to backup file
  777.       '
  778.       While SQSIZE>0
  779.          If FLPY : DISKUSED=DISKFREE-Dfree : End If
  780.          If DISKFREE-DISKUSED<4096 : Close 1
  781.             Wait 5 : Inc NUMDISKS : REQUEST_BACKDISC[NUMDISKS]
  782.          End If
  783.          If Lof(1)>221184 : Inc SPLITNUM
  784.             Right$(DESTFILE$,1)=Chr$(SPLITNUM+48) : Close 1
  785.             Wait 5 : Trap Kill DESTFILE$ : Open Out 1,DESTFILE$
  786.          End If : BLEN=Min(SQSIZE,1024)
  787.          Print #1,Peek$(AD,BLEN); : Add AD,BLEN : Add SQSIZE,-BLEN
  788.          Add DISKUSED,BLEN : Dialog Update 2,3,0,DISKUSED/64,DISKFREE/64
  789.       Wend : Print "Done." : Wait 20
  790.    Else
  791.       HMSG$="FAILED! Not enough memory to load file!" : Print HMSG$
  792.    End If : HISTORYENTRY["  "+HMSG$+LF$]
  793.    '
  794. End Proc
  795. '
  796. ' Restore Procedures
  797. '
  798. Procedure CREATE_DIR[DR$]
  799.    '
  800.    ' create directory structure DR$ if not exist
  801.    '
  802.    DR$=Extpath$(DR$) : PS=Instr(DR$,"/")
  803.    While PS : TT$=Left$(DR$,PS-1)
  804.       If Not Exist(TT$) : Mkdir TT$ : End If : PS=Instr(DR$,"/",PS+1)
  805.    Wend
  806. End Proc
  807. Procedure REQUEST_RESTDISC[DN]
  808.    '
  809.    ' wait for next backup disc in drive DF0:
  810.    '
  811.    Get Block 8,0,0,640,232 : Wait Vbl : Ink 0,3
  812.    Set Pattern 30 : Bar 0,0 To 639,231 : Set Pattern 0
  813.    TT$=Lzstr$(DN,4) : SPLITNUM=0 : NAME$=BKNAME$+"_#"+TT$+":"
  814.    Do
  815.       '
  816.       ' remove previous backup disc from drive DF0:
  817.       '
  818.       Dialog Open 3,3 : Vdialog$(3,0)="Please remove disc from DF0:"
  819.       RR=Dialog Run(3) : Repeat : Until Not Exist("DF0:") : Dialog Close 3
  820.       '
  821.       ' ask for next backup disc; check for backup file
  822.       '
  823.       Dialog Open 3,3 : Vdialog$(3,0)="Please insert '"+NAME$+"' into DF0:"
  824.       RR=Dialog Run(3) : Repeat : Until Exist(NAME$) : Dialog Close 3
  825.       '
  826.       ' check for required backup file
  827.       '
  828.       SOURCE$="DF0:Backup"+TT$+".DAT0" : Exit If Exist(SOURCE$)
  829.       INFO["Hey, can't find backup data what I expected!"]
  830.    Loop : Put Block 8 : Del Block 8 : Wait Vbl
  831.    '
  832. End Proc
  833. Procedure RESTOR_FILE[FILE$,INFO$]
  834.    '
  835.    ' update history; extract file informations
  836.    '
  837.    Reserve As Work 20,26
  838.    AD=Start(20) : Poke$ AD,INFO$ : FLSIZE=Leek(AD) : FLSUMM=Leek(AD+4)
  839.    SQSIZE=Leek(AD+8) : SQSUMM=Leek(AD+12) : FLDATE=Leek(AD+16)
  840.    FLTIME=Leek(AD+20) : FLPROT=Deek(AD+24) : Cls 6,56,104 To 584,128
  841.    Erase 20 : Print At(7,13);Right$(FILE$,66) : Locate 9,14
  842.    HISTORYENTRY["("+Ct Time$(Current Time)+") Loading '"+FILE$+"'"]
  843.    '
  844.    ' special check for empty files
  845.    '
  846.    If FLSIZE=0 : OKAY=True
  847.       MS$="Okay." : HMSG$="Saving empty file... " : Print HMSG$;
  848.       If NOSIMULATE
  849.          TT$=Path$(FILE$) : If Not Exist(TT$) : CREATE_DIR[TT$] : End If
  850.          MS$="Failed!" : OKAY=False : Trap Open Out 2,FILE$
  851.          If Errtrap=0 : Close 2 : Set Object Date FILE$,FLDATE,FLTIME
  852.             Protect Object FILE$,FLPROT : MS$="Done." : OKAY=True
  853.          End If
  854.       End If : HMSG$=HMSG$+MS$ : Print MS$ : Wait 5
  855.    Else
  856.       SZ=SQSIZE : BLEN=(SZ+3) and $FFFFFFFC : Print "Loading data... ";
  857.       Reserve As Work 20,BLEN : AD=Start(20) : Fill AD To AD+BLEN,0
  858.       Repeat
  859.          '
  860.          ' check next backup file or new disc ?
  861.          '
  862.          If Eof(1) : Close 1 : Wait 5
  863.             Inc SPLITNUM : Right$(SOURCE$,1)=Chr$(SPLITNUM+48)
  864.             If Not Exist(SOURCE$)
  865.                Inc NUMDISKS : REQUEST_RESTDISC[NUMDISKS]
  866.             End If : Open In 1,SOURCE$
  867.          End If
  868.          '
  869.          ' writing data into temporary bank 20
  870.          '
  871.          Poke$ AD,Input$(1,Min(SZ,1024)) : Wait Vbl : SZ=Max(SZ-1024,0)
  872.          Add AD,1024 : Dialog Update 2,2,0,(SQSIZE-SZ)/256,SQSIZE/256
  873.       Until SZ<1
  874.       Wait 10 : Print "Done." : Locate 11,15 : HMSG$="" : OKAY=False
  875.       '
  876.       ' check if data are (power) packed -> try to unpack it
  877.       '
  878.       If SQSIZE<FLSIZE : HMSG$="Unpacking... " : Print HMSG$;
  879.          If Bank Checksum(20)=SQSUMM
  880.             Change Mouse 5 : Flash 0,SQFLSH$ : Trap Ppunpack 20 To 22
  881.             Wait 5 : Flash Off : Colour 0,0 : Change Mouse 4
  882.             '
  883.             ' if unpacking successful, replace original data in bank 20
  884.             '
  885.             If Errtrap=0 : BLEN=(FLSIZE+3) and $FFFFFFFC
  886.                Erase 20 : Reserve As Work 20,BLEN : AD=Start(22)
  887.                Copy AD,AD+BLEN To Start(20) : Wait 5 : Erase 22
  888.             Else : FLSIZE=0
  889.                HMSG$="Unpacking error! (Code:"+Str$(Errtrap)+")"
  890.             End If
  891.          Else
  892.             HMSG$="Data checksum error!" : FLSIZE=0
  893.          End If
  894.       End If
  895.       '
  896.       ' if (unpacked) data checksum okay, save file
  897.       '
  898.       If FLSIZE
  899.          If Bank Checksum(20)=FLSUMM : MS$="Okay." : OKAY=True
  900.             If NOSIMULATE : OKAY=False : TT$=Path$(FILE$)
  901.                If Not Exist(TT$) : CREATE_DIR[TT$] : End If
  902.                MS$="Saving... " : Print MS$; : HMSG$=HMSG$+MS$
  903.                AD=Start(20) : Trap Bsave FILE$,AD To AD+FLSIZE
  904.                If Errtrap=0 : Set Object Date FILE$,FLDATE,FLTIME
  905.                   Protect Object FILE$,FLPROT : MS$="Done." : OKAY=True
  906.                Else : MS$="Failed! (Code:"+Str$(Errtrap)+")" : End If
  907.             End If : HMSG$=HMSG$+MS$ : Print MS$; : Wait 10
  908.          Else
  909.             HMSG$="File checksum error!"
  910.          End If
  911.       End If
  912.    End If : HISTORYENTRY["  "+HMSG$+LF$]
  913.    '
  914. End Proc[OKAY]
  915. '
  916. ' History Procedures
  917. '
  918. Procedure HISTORY_SAVE
  919.    '
  920.    ' save history messages
  921.    '
  922.    FL$=Fsel$("*.TXT",BKNAME$+"Log.TXT","Save history messages")
  923.    If FL$>"" : Open Out 2,FL$ : AD=HISTROOTADRS
  924.       While AD
  925.          Print #2,Peek$(AD+8,Leek(AD),C0$);LF$; : AD=Leek(AD+4)
  926.       Wend : Close 2
  927.    End If
  928. End Proc
  929. Procedure HISTORYENTRY[MS$]
  930.    '
  931.    ' add new history message (note: GLOBAL address variables!!!)
  932.    '
  933.    ALLOCMEM[Len(MS$)+8]
  934.    If Param : ADRS=Param : Inc NUMHIST
  935.       If HISTADRS : Loke HISTADRS+4,ADRS : End If : Poke$ ADRS+8,MS$
  936.       If HISTROOTADRS=0 : HISTROOTADRS=ADRS : End If : HISTADRS=ADRS
  937.    End If
  938. End Proc
  939. Procedure DISPLAY_HISTORY[HTOP]
  940.    '
  941.    ' display backup history messages
  942.    '
  943.    MOVE_TO_ENTRY[HISTROOTADRS,HTOP] : AD=Param : Paper 0 : Pen 3
  944.    For YP=4 To 11 : TT$=Peek$(AD+8,64,C0$) : LL=Len(TT$)
  945.       If Right$(TT$,1)=LF$ : Dec LL : TT$=Left$(TT$,LL) : End If
  946.       Print At(7,YP);TT$;Space$(64-LL) : AD=Leek(AD+4) : Exit If AD=0
  947.    Next : Paper 6 : Pen 2
  948. End Proc
  949. '
  950. ' Directory Tree Procedures
  951. '
  952. Procedure MAKE_DIRTREE[ROOT$]
  953.    '
  954.    ' dynamically build directory tree starting at ROOT$
  955.    ' returns TREEROOT on success, 0 if user abort, -1 if out of memory
  956.    '
  957.    ' Important vars:
  958.    '   TREEROOT ..... pointer to created directory tree structure
  959.    '   TREETHIS ..... pointer to current dir item of tree structure
  960.    '   STACKADR ..... pointer to top element of "dirs-to-do" stack
  961.    '   DRLSTADR ..... pointer to first element of sub dirs list
  962.    '
  963.    ' Directory stack:
  964.    '   NALLOC (4,+ 0) ... bytes allocated for this item (ALLOCMEM)
  965.    '   PRVPTR (4.+ 4) ... address to previous item (it's a stack!)
  966.    '   PARPTR (4,+ 8) ... address to parent item of dir tree
  967.    '   DNAME$ (D,+12) ... tree structure, », complete path of dir
  968.    '
  969.    QUIT=False : TT$="»"+ROOT$ : ALLOCMEM[Len(TT$)+9] : ADRS=Param
  970.    Poke$ ADRS+12,TT$ : STACKADR=ADRS : TREEROOT=0 : TREETHIS=0
  971.    MXTREE=0 : NUMDIRS=0 : NUMFILES=0 : NUMBYTES=0 : SELBYTES=0
  972.    '
  973.    ' as long as there are items on stack read and remove top element
  974.    '
  975.    While STACKADR
  976.       Inc MXTREE : AD=STACKADR : TT$=Peek$(AD+12,Leek(AD),C0$)
  977.       PARNTADR=Leek(AD+8) : PS=Instr(TT$,"»") : TREE$=Left$(TT$,PS-1)+"»"
  978.       DR$=Mid$(TT$,PS+1) : STACKADR=Leek(STACKADR+4) : DEALLOCMEM[AD]
  979.       If TREEROOT : TT$=Filename$(DR$) Else TT$=DR$ : End If : NBYTES=0
  980.       '
  981.       ' read directory, put dirs and files on seperate lists
  982.       '
  983.       TR$=TREE$+TT$+C0$ : If Right$(DR$,1)<>":" : DR$=DR$+"/" : End If
  984.       NDIRS=0 : NFILES=0 : DRLSTADR=0 : FLISTADR=0 : Examine Dir DR$
  985.       Do
  986.          FL$=Examine Next$ : Exit If FL$=""
  987.          If Object Type>0 : Inc NDIRS
  988.             '
  989.             ' sort directory into linked list of sub dirs (descending)
  990.             '
  991.             ALLOCMEM[Len(FL$)+5] : ADRS=Param : Poke$ ADRS+8,FL$
  992.             If DRLSTADR : STRT=DRLSTADR : PREV=0 : FL$=Upper$(FL$)
  993.                While Upper$(Peek$(STRT+8,Leek(STRT),C0$))>FL$
  994.                   PREV=STRT : STRT=Leek(STRT+4) : Exit If STRT=0
  995.                Wend
  996.                If PREV
  997.                   Loke PREV+4,ADRS : If STRT : Loke ADRS+4,STRT : End If
  998.                Else : DRLSTADR=ADRS : Loke ADRS+4,STRT : End If
  999.             Else
  1000.                DRLSTADR=ADRS
  1001.             End If
  1002.          Else
  1003.             '
  1004.             ' sort file into linked list (ascending)
  1005.             '
  1006.             ALLOCMEM[Len(FL$)+13] : ADRS=Param : Add NBYTES,Object Size
  1007.             Loke ADRS+8,Object Size : Poke$ ADRS+12,FL$ : Inc NFILES
  1008.             If FLISTADR : STRT=FLISTADR : PREV=0 : FL$=Upper$(FL$)
  1009.                While Upper$(Peek$(STRT+12,Leek(STRT),C0$))<FL$
  1010.                   PREV=STRT : STRT=Leek(STRT+4) : Exit If STRT=0
  1011.                Wend
  1012.                If PREV
  1013.                   Loke PREV+4,ADRS : If STRT : Loke ADRS+4,STRT : End If
  1014.                Else : FLISTADR=ADRS : Loke ADRS+4,STRT : End If
  1015.             Else
  1016.                FLISTADR=ADRS
  1017.             End If
  1018.          End If
  1019.       Loop
  1020.       '
  1021.       ' add new entry to directory tree; update counters
  1022.       '
  1023.       ALLOCMEM[Len(TR$)+NFILES+24] : ADRS=Param : NR=NFILES+1
  1024.       If TREETHIS : Loke TREETHIS+4,ADRS Else TREEROOT=ADRS : End If
  1025.       Loke ADRS+8,PARNTADR : Loke ADRS+12,FLISTADR : Loke ADRS+16,NBYTES
  1026.       Doke ADRS+24,NFILES : Poke ADRS+26,PS : TREETHIS=ADRS : AD=ADRS+27
  1027.       While NR : Poke AD,46 : Inc AD : Dec NR : Wend : Poke$ AD,TR$
  1028.       Add NUMDIRS,NDIRS : Add NUMFILES,NFILES : Add NUMBYTES,NBYTES
  1029.       '
  1030.       ' check if any sub dirs found; if so recalcuate tree structure
  1031.       '
  1032.       If DRLSTADR
  1033.          NR=Len(TREE$)-1 : TR$=""
  1034.          While NR : AC=Asc(Mid$(TREE$,NR)) : Dec NR
  1035.             If AC=32 or AC=45 : TR$=" "+TR$ Else TR$="|"+TR$ : End If
  1036.          Wend
  1037.          '
  1038.          ' put sub dirs on stack; free memory from sub dir items
  1039.          '
  1040.          STRT=DRLSTADR : DR$="-»"+DR$
  1041.          Repeat : TT$=TR$+DR$+Peek$(STRT+8,Leek(STRT),C0$)
  1042.             ALLOCMEM[Len(TT$)+9] : ADRS=Param : Left$(DR$,1)="+"
  1043.             Loke ADRS+4,STACKADR : Loke ADRS+8,TREETHIS : Poke$ ADRS+12,TT$
  1044.             STACKADR=ADRS : AD=STRT : STRT=Leek(STRT+4) : DEALLOCMEM[AD]
  1045.          Until STRT=0
  1046.       End If
  1047.       '
  1048.       ' check abort; check memory: cancel if lower than 64K left
  1049.       '
  1050.       Print At(30,14); Using "######";NUMDIRS
  1051.       Print At(46,14); Using "########";NUMFILES
  1052.       NR=Chip Free+Fast Free : Print At(37,16); Using "########";NR
  1053.       QUIT=Dialog(3) : If NR<65536 : QUIT=True : End If : Exit If QUIT
  1054.    Wend
  1055.    '
  1056.    ' user abort ? -> free dir stack and already created dir tree
  1057.    '
  1058.    If QUIT : DELETE_DIRTREE[TREEROOT] : DELETE_LIST[STACKADR]
  1059.       If QUIT<0 : TREEROOT=-1 Else TREEROOT=0 : End If
  1060.    End If
  1061.    '
  1062. End Proc[TREEROOT]
  1063. Procedure DELETE_DIRTREE[ADRS]
  1064.    '
  1065.    ' removes directory tree (with file list) starting at ADRS
  1066.    '
  1067.    While ADRS : DELETE_LIST[Leek(ADRS+12)]
  1068.       AD=ADRS : ADRS=Leek(ADRS+4) : DEALLOCMEM[AD]
  1069.    Wend
  1070. End Proc
  1071. Procedure CREATE_DIRTREE_PATH[ADRS]
  1072.    '
  1073.    ' extract full path name of the entry at ADRS (ends with "/")
  1074.    '
  1075.    While ADRS
  1076.       TT$=Peek$(ADRS+Deek(ADRS+24)+28,Leek(ADRS),C0$)
  1077.       If Right$(TT$,1)<>":" : TT$=TT$+"/" : End If
  1078.       PT$=Mid$(TT$,Instr(TT$,"»")+1)+PT$ : ADRS=Leek(ADRS+8)
  1079.    Wend
  1080. End Proc[PT$]
  1081. Procedure MOVE_TO_ENTRY[ROOTADRS,DTOP]
  1082.    '
  1083.    ' moves to entry DTOP of directory tree or file list
  1084.    '
  1085.    If ROOTADRS>0 : AD=ROOTADRS
  1086.       While DTOP : AD=Leek(AD+4) : Dec DTOP : Exit If AD=0 : Wend
  1087.    End If
  1088. End Proc[AD]
  1089. '
  1090. ' System Memory Procedures
  1091. '
  1092. Procedure ALLOCMEM[BYTE]
  1093.    '
  1094.    ' allocate memory from system:
  1095.    '  -> add 4 bytes for number of bytes allocated information
  1096.    '  -> attributes: ANY =0 , PUBLIC =1 , CLEAR =65536 ==> $10001
  1097.    '  -> write number of bytes into first 4 bytes (NEVER CHANGE!)
  1098.    ' RETURN: start address, or 0 if memory block not available
  1099.    '
  1100.    BYTE=(BYTE+7) and $FFFFFFFC : Dreg(0)=BYTE : Dreg(1)=$10001
  1101.    ADRS=Execall(-198) : If ADRS : Loke ADRS,BYTE : End If
  1102.    '
  1103. End Proc[ADRS]
  1104. Procedure DEALLOCMEM[ADRS]
  1105.    '
  1106.    ' free memory allocated by procedure ALLOCMEM[] above
  1107.    '  -> first read allocated bytes from first 4 bytes (CAUTION!)
  1108.    '  -> free memory (read required addresses before calling this)
  1109.    '
  1110.    If ADRS : Areg(1)=ADRS : Dreg(0)=Leek(ADRS) : RT=Execall(-210) : End If
  1111.    '
  1112. End Proc
  1113. Procedure DELETE_LIST[ADRS]
  1114.    '
  1115.    ' remove any linked list created with ALLOCMEM[] using DEALLOCMEM[]
  1116.    '  -> IMPORTANT: first 4 bytes are amount of bytes allocated
  1117.    '  -> IMPORTANT: second 4 bytes are address to next item
  1118.    '
  1119.    While ADRS>0 : AD=ADRS : ADRS=Leek(ADRS+4) : DEALLOCMEM[AD] : Wend
  1120.    '
  1121. End Proc
  1122. Procedure FLOPPYADDBUFFERS[NR]
  1123.    '
  1124.    ' call DOS function: add NR buffers for internal floppy "DF0:"
  1125.    ' RETURN: number of buffers, or 0 if failed (drive maybe busy ?)
  1126.    '
  1127.    TT$="DF0:" : Dreg(1)=Varptr(TT$)
  1128.    Dreg(2)=NR : RS=Doscall(Lvo("AddBuffers"))
  1129.    '
  1130.    ' if function returns -1, IoErr has number of buffers (obsolete?)
  1131.    '
  1132.    If RS<0 : RS=Doscall(Lvo("IoErr")) : End If
  1133.    '
  1134. End Proc[RS]
  1135. '
  1136. ' Global Procedures
  1137. '
  1138. Procedure ALERT[MESS$]
  1139.    '
  1140.    ' alert program; interrupt Dialog Box with <CTRL>+'C' and Break Off !!!
  1141.    '
  1142.    Dialog Open 6,2 : Vdialog$(6,0)=MESS$ : SL=Dialog Run(6) : Wait Vbl
  1143.    Repeat : Multi Wait : SL=Vdialog(6,1) : Until SL : Dialog Close 6
  1144. End Proc[SL]
  1145. Procedure INFO[MESS$]
  1146.    '
  1147.    ' info box; interrupt Dialog Box with <CTRL>+'C' and Break Off !!!
  1148.    '
  1149.    Dialog Open 7,3 : Vdialog$(7,0)=MESS$ : RR=Dialog Run(7) : Wait Vbl
  1150.    Repeat : Multi Wait : Until Mouse Click or Inkey$>"" : Dialog Close 7
  1151. End Proc
  1152.  
  1153.